/**
 * 
 */
package template.page.user;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.click.ActionListener;
import org.apache.click.Context;
import org.apache.click.Control;
import org.apache.click.control.AbstractLink;
import org.apache.click.control.ActionButton;
import org.apache.click.control.ActionLink;
import org.apache.click.control.Column;
import org.apache.click.control.Decorator;
import org.apache.click.control.Label;
import org.apache.click.control.Table;
import org.apache.click.dataprovider.DataProvider;
import org.apache.click.extras.control.LinkDecorator;
import org.apache.click.util.Bindable;
import org.apache.click.util.HtmlStringBuffer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.PredicateUtils;

import template.page.BorderPage;
import cvcg.dto.GameSessionVoteDTO;
import cvcg.model.Game;
import cvcg.model.GameSession;

/**
 * @author jaracje
 *
 */
@SuppressWarnings({ "rawtypes", "unchecked","serial" })
public class GameSessionDetailPhase1 extends BorderPage 
{	 
	public String title = "Phase 1 (List)";
	public static final int MAX_VOTES = 7;
		
	private Table attendingPlayerTable = new Table("attendingPlayerTable");
	private Table voteTable = new Table("voteTable");
	private Table knownGameTable = new Table("knownGameTable");
	private Table availableShortGameTable = new Table("availableShortGameTable");
	private Table availableNormalGameTable = new Table("availableNormalGameTable");
	private Table availableHeavyGameTable = new Table("availableHeavyGameTable");
	private Label gameSessionDateLabel = new Label("gameSessionDate");
	private Label playerVotesLabel = new Label("playerVotes");
	private Label maxVotesLabel = new Label("maxVotes");
	private List<Game> allAvailableGames;
	private GameSession currentGameSession;
	private ActionLink voteLink = new ActionLink("vote",this,"onVoteClick");	
	private ActionLink removeVoteLink = new ActionLink("removeVote",this,"onRemoveVoteClick");	
	private Set<Long> votedGameIds = new HashSet<Long>();
	private ActionButton backButton = new ActionButton("backButton","back");
	
	@Bindable protected Long id;
	
	public GameSessionDetailPhase1() 
	{
		addControl(gameSessionDateLabel);
		addControl(attendingPlayerTable);
		addControl(knownGameTable);
		addControl(availableShortGameTable);		
		addControl(availableNormalGameTable);
		addControl(availableHeavyGameTable);
		addControl(voteLink);
		addControl(removeVoteLink);
		addControl(voteTable);
		addControl(playerVotesLabel);
		maxVotesLabel.setLabel(""+MAX_VOTES);
		addControl(maxVotesLabel);
		addControl(backButton);
		backButton.setListener(this, "onBackClick");
				
		// Attending player table
		attendingPlayerTable.setClass(Table.CLASS_ITS);
		attendingPlayerTable.setWidth("100%");
		attendingPlayerTable.setSortable(false);

		Column dateColumn = new Column("joinDate");
		dateColumn.setFormat("{0,date,dd/MM/yyyy HH:mm}");
		attendingPlayerTable.addColumn(dateColumn);
		attendingPlayerTable.addColumn(new Column("playerName"));
		attendingPlayerTable.addColumn(new Column("ownedGameCount"));
		attendingPlayerTable.addColumn(new Column("knownGameCount"));
		attendingPlayerTable.setSortedColumn("joinDate");
		
		voteTable.setClass(Table.CLASS_ITS);
		voteTable.setSortable(false);			
		voteTable.setWidth("100%");
		
		Column iconCol = new Column("cat");

		iconCol.setDecorator(new Decorator() {
		     public String render(Object row, Context context) {
		         GameSessionVoteDTO gameSessionVoteDTO = (GameSessionVoteDTO) row;		         		         
		         return gameSessionVoteDTO.getDurationDecorator();
		     }
		 });
		voteTable.addColumn(iconCol);
		voteTable.addColumn(new Column("gameName"));
		voteTable.addColumn((new Column("minPlayer")));
		voteTable.addColumn(new Column("maxPlayer"));
		voteTable.addColumn(new Column("duration"));
		voteTable.addColumn(new Column("votes"));		
		voteTable.setSortedColumn("votes");
		voteTable.setSortedAscending(false);
		
	    // Table rowList will be populated through a DataProvider which loads
	    // data on demand.
		attendingPlayerTable.setDataProvider(new DataProvider() 
		{	        
			public List getData() 
	        {
	        	List attendingPlayers = new ArrayList();
	        	if (currentGameSession!=null) 
	        	{
	        		attendingPlayers.addAll(currentGameSession.getAttendingPlayers());
	        	}
	            return attendingPlayers;	        
	        }
	    });

	    // Below we setup the table to preserve it's state (sorting and paging)
	    // while editing customers
		attendingPlayerTable.getControlLink().setActionListener(new ActionListener() 
		{
	
	        public boolean onAction(Control source) 
	        {
	            // Save Table sort and paging state between requests.
	            // NOTE: we set the listener on the table's Link control which is invoked
	            // when the Link is clicked, such as when paging or sorting.
	            // This ensures the table state is only saved when the state changes, and
	            // cuts down on unnecessary session replication in a cluster environment.
	        	attendingPlayerTable.saveState(getContext()); 
	            return true;
	        }
	    });
	
	    // Restore the table sort and paging state from the session between requests
		attendingPlayerTable.restoreState(getContext());
		
		voteTable.setDataProvider(new DataProvider() 
		{	        
			public List getData() 
	        {
	        	//List votes = new ArrayList();
        		//votes.addAll(gameSessionService.getGameSessionVotes(id));
	            //return votes;
				return gameSessionService.getGameSessionVotes(id);
	        }
	    });

	    // Below we setup the table to preserve it's state (sorting and paging)
	    // while editing customers
		voteTable.getControlLink().setActionListener(new ActionListener() 
		{
	
	        public boolean onAction(Control source) 
	        {
	            // Save Table sort and paging state between requests.
	            // NOTE: we set the listener on the table's Link control which is invoked
	            // when the Link is clicked, such as when paging or sorting.
	            // This ensures the table state is only saved when the state changes, and
	            // cuts down on unnecessary session replication in a cluster environment.
	        	voteTable.saveState(getContext()); 
	            return true;
	        }
	    });
	
	    // Restore the table sort and paging state from the session between requests
		voteTable.restoreState(getContext());

		
		// Known games table
		populateGameTable(knownGameTable);
		populateGameTable(availableShortGameTable);
		populateGameTable(availableNormalGameTable);
		populateGameTable(availableHeavyGameTable);				
	}
	
	private void addRemoveVoteControl() 
	{
		addRemoveVoteColumn(voteTable);
	}

	private void addRemoveVoteColumn(Table table) 
	{
        Column column = new Column("Action");
        column.setTextAlign("center");                
        column.setSortable(false);
        LinkDecorator decorator = new LinkDecorator(table, removeVoteLink, "gameId") 
        {               
		  protected void renderActionLink(HtmlStringBuffer buffer, AbstractLink link, Context context, Object row, Object value) 
		  { 
			    Long gameId = ((GameSessionVoteDTO)row).getGameId();
			    if (!votedGameIds.contains(gameId)) 
			    {
			    	link.setDisabled(true);
			    	link.setLabel("");
			    	link.setTitle("");
			    	link.setImageSrc("");
			    } else {
			    	link.setDisabled(false);
			    	link.setLabel("Remove Vote");
			    	link.setTitle("Remove Vote");
			    	link.setImageSrc("/assets/images/remove_vote.png");
			    }
			  	link.setParameter("id", id);                 
		        super.renderActionLink(buffer, link, context, row, value); 
		  } 
        }; 
       column.setDecorator(decorator);
       table.addColumn(column);
	}

	private void addVoteControl() 
	{		
		addVoteColumn(knownGameTable);
		addVoteColumn(availableShortGameTable);
		addVoteColumn(availableNormalGameTable);
		addVoteColumn(availableHeavyGameTable);
	}
	
	private void addVoteColumn(Table table) 
	{
        Column column = new Column("Action");
        column.setTextAlign("center");                
        column.setSortable(false);
        LinkDecorator decorator = new LinkDecorator(table, voteLink, "id") 
        {               
          protected void renderActionLink(HtmlStringBuffer buffer, AbstractLink link, Context context, Object row, Object value) {
        	  	Long gameId = ((Game)row).getId();
			    if (votedGameIds.contains(gameId) || votedGameIds.size()>=MAX_VOTES) 
			    {
			    	link.setDisabled(true);		
			    	link.setLabel("");
			    	link.setTitle("");
			    	link.setImageSrc("");
			    } else {			    	
			    	link.setParameter("id", id);
			    	link.setDisabled(false);
					link.setImageSrc("/assets/images/add_vote.png");
					link.setLabel("Vote");
					link.setTitle("Vote");
			    }
                super.renderActionLink(buffer, link, context, row, value); 
            } 
        }; 
       column.setDecorator(decorator);
       table.addColumn(column);
	}
	
	@Override
	public void onInit() 
	{	
		super.onInit();
		String currentUser = getCurrentUser();
		currentGameSession = getGameSessionService().getGameSessionById(id);
		if (currentGameSession!=null) 
		{
			votedGameIds = currentGameSession.getVotedGameIdByPlayerName(currentUser);
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
			gameSessionDateLabel.setLabel(sdf.format(currentGameSession.getDate()));
			allAvailableGames = currentGameSession.getAvailableGames();
			if (currentGameSession.isPlayerAttendingSession(currentUser)) 
			{
				addVoteControl();
				addRemoveVoteControl();				
			}
		}		
	}
	
	
	
	private void populateGameTable(final Table gameTable) 
	{
		gameTable.setClass(Table.CLASS_ITS);
		gameTable.setSortable(false);
		gameTable.setWidth("100%");
		gameTable.addColumn(new Column("name"));
		gameTable.addColumn(new Column("minPlayer"));
		gameTable.addColumn(new Column("maxPlayer"));
		gameTable.addColumn(new Column("duration"));
		gameTable.setSortedColumn("name");
		
	    // Table rowList will be populated through a DataProvider which loads
	    // data on demand.
		gameTable.setDataProvider(new DataProvider() 
		{	        
			public List getData() 
	        {
				return getGameTableDataProvider(gameTable);       
	        }
	    });

	    // Below we setup the table to preserve it's state (sorting and paging)
	    // while editing customers
		gameTable.getControlLink().setActionListener(new ActionListener() 
		{
	
	        public boolean onAction(Control source) 
	        {
	            // Save Table sort and paging state between requests.
	            // NOTE: we set the listener on the table's Link control which is invoked
	            // when the Link is clicked, such as when paging or sorting.
	            // This ensures the table state is only saved when the state changes, and
	            // cuts down on unnecessary session replication in a cluster environment.
	        	gameTable.saveState(getContext()); 
	            return true;
	        }
	    });
	
	    // Restore the table sort and paging state from the session between requests
		gameTable.restoreState(getContext()); 

	}
	
	private List getGameTableDataProvider(Table gameTable) 
	{		
		if (currentGameSession!=null) 
		{
			if (gameTable.equals(knownGameTable)) 
			{
				return currentGameSession.getAvailableKnownGames();   
			} else {
				String methodName = "isNormalGame";
				List<Game> availableGames = new ArrayList<Game>();
				availableGames.addAll(allAvailableGames);
				if (gameTable.equals(availableShortGameTable)) 
				{
					methodName = "isShortGame";
				} else if (gameTable.equals(availableHeavyGameTable)) 
				{
					methodName = "isHeavyGame";
				}			
				CollectionUtils.filter(availableGames,PredicateUtils.invokerPredicate(methodName));
	            return 	availableGames;        
			}
		}
		return null;
	}
	
	public boolean onVoteClick() 
	{
			String currentUser = getCurrentUser();
			Long gameId = voteLink.getValueLong();
			gameSessionService.addGameSessionVote(id, gameId, currentUser);		
			votedGameIds = gameSessionService.getVotedGameIdByGameSessionIdAndPlayerName(id, currentUser);
			return true;
	}
	
	public boolean onRemoveVoteClick() 
	{
		String currentUser = getCurrentUser();
		Long gameId = removeVoteLink.getValueLong();
		gameSessionService.removeGameSessionVote(id, gameId, currentUser);
		votedGameIds = gameSessionService.getVotedGameIdByGameSessionIdAndPlayerName(id, currentUser);
		return true;
	}

	@Override
	public void onRender() {
		playerVotesLabel.setLabel(""+votedGameIds.size());		
		super.onRender();
	}	
	
	/**
     * Handle the back click event.
     */    
    public boolean onBackClick() 
    {
    	setRedirect(HomePage.class);        
        return true;
    }
}
